﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace Interfleet.SE.UICompiler.Core.Batch
{
    /// <summary>
    /// This class represents a persisted compilation. It will xml read data from a file
    /// and return the values needed to run the compilation.
    /// </summary>
    public class BatchJob
    {
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="batchFilePath">Full path of the requested batch file</param>
        public BatchJob(string batchFilePath)
            : this(batchFilePath, new FileProvider())
        {
            
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="batchFilePath">Full path of the requested batch file</param>
        /// <param name="fileProvider">An instance of <see cref="IFileProvider"/></param>
        public BatchJob(string batchFilePath, IFileProvider fileProvider)
        {
            if (string.IsNullOrEmpty(batchFilePath))
            {
                throw new ArgumentNullException("batchFilePath");
            }
            _batchFilePath = batchFilePath;
            _xElement = XElement.Parse(fileProvider.ReadFileToEnd(batchFilePath));
            ParseElement();
        }

        private string _batchFilePath;
        private XElement _xElement;

        private void ParseElement()
        {
            SetCompileType();
            SetFiles();
            SetOutputFile();
            SetCompileOption();
        }

        private void Throw(string expectedNode)
        {
            throw new InvalidBatchXmlException(expectedNode);
        }

        private void Throw(string expectedNode, string expectedAttribute)
        {
            throw new InvalidBatchXmlException(expectedNode, expectedAttribute);
        }

        private void SetCompileType()
        {
            if (_xElement.Attribute("compileSupplier") != null)
            {
                var supplier = (CompileSupplier)Enum.Parse(typeof(CompileSupplier), _xElement.Attribute("compileSupplier").Value);
                CompileType = CompileType.FromSupplier(supplier);
            }
            else
            {
                Throw("/Batch", "compileSupplier");
            }
        }

        private void SetCompileOption()
        {
            if (_xElement.Attribute("compileOption") != null)
            {
                var option = _xElement.Attribute("compileOption").Value;
                CompileOption = option;
            }
        }

        private void SetFiles()
        {
            var files = new List<string>();
            var fileElems = _xElement.Descendants("File");
            if (fileElems == null)
            {
                Throw("/BatchFiles/File");
            }
            foreach (var fileNode in fileElems)
            {
                files.Add(fileNode.Value);
            }
            Files = files;
        }

        private void SetOutputFile()
        {
            var file = _xElement.Attribute("outputFile");
            if (file == null)
            {
                Throw("/Batch", "outputFile");
            }
            OutputFile = file.Value;
        }

        public void DecorateArguments(Arguments arguments)
        {
            arguments.CompileOption = CompileOption;
            arguments.CompiledFileName = OutputFile;
            foreach (var file in Files)
            {
                arguments.Files.Add(file);
            }
        }

        /// <summary>
        /// Compile type
        /// </summary>
        public CompileType CompileType
        {
            get;
            private set;
        }

        /// <summary>
        /// Compile option of the batch job
        /// </summary>
        public string CompileOption
        {
            get;
            private set;
        }

        /// <summary>
        /// The input files (full paths required)
        /// </summary>
        public IEnumerable<string> Files
        {
            get;
            private set;
        }

        /// <summary>
        /// The output file (full paths required)
        /// </summary>
        public string OutputFile
        {
            get;
            private set;
        }
    }
}
